package com.ruoyi.system.service.impl;

import com.ruoyi.system.domain.RedisDataInfo;
import com.ruoyi.system.service.ISysRedisService;
import com.ruoyi.system.service.ISysRedisValueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author wjialong
 */
@Service
public class SysRedisValueServiceImpl implements ISysRedisValueService {
    @Autowired
    ISysRedisService redisService;

    @Override
    public boolean getValue(RedisDataInfo redisDataInfo) {
        StringRedisTemplate redisTemplate = redisService.getRedisTemplate(redisDataInfo);
        String key = redisDataInfo.getKey();
        // 根据分类设置数据
        try {
            // 设置ttl
            redisDataInfo.setTtl(redisTemplate.getExpire(key));
            redisDataInfo.setType(redisTemplate.type(key));
            switch (redisDataInfo.getType()) {
                case LIST:
                    ListOperations<String, String> opsForList = redisTemplate.opsForList();
                    redisDataInfo.setSize(opsForList.size(key));
                    redisDataInfo.setValue(opsForList.range(key, 0, redisDataInfo.getSize() - 1));
                    break;
                case STRING:
                    redisDataInfo.setValue(redisTemplate.opsForValue().get(key));
                    break;
                case HASH:
                    HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();
                    String value = (String) redisDataInfo.getValue();
                    // 存在pattern
                    if (value != null && !value.isEmpty()) {
                        Map<Object, Object> map = new HashMap<>();
                        Cursor<Map.Entry<Object, Object>> scan =
                                opsForHash.scan(key, ScanOptions.scanOptions().match(value).build());

                        // 遍历搜索结果
                        while (scan.hasNext()) {
                            Map.Entry<Object, Object> next = scan.next();
                            map.put(next.getKey(), next.getValue());
                        }

                        redisDataInfo.setValue(map);
                        break;
                    }

                    // 不存在pattern就直接拿
                    Map<Object, Object> map = opsForHash.entries(key);
                    redisDataInfo.setValue(map);
                    break;
                case SET:
                    SetOperations<String, String> opsForSet = redisTemplate.opsForSet();
                    Set<String> set = opsForSet.members(key);
                    redisDataInfo.setValue(set);
                    break;
                case ZSET:
                    ZSetOperations<String, String> opsForZSet = redisTemplate.opsForZSet();
                    redisDataInfo.setValue(opsForZSet.rangeWithScores(key, 0, opsForZSet.zCard(key)));
                default:
            }
        } catch (Exception e) {
            return false;
        } finally {
            redisTemplate.getConnectionFactory().getConnection().close();
        }
        return true;
    }

    @Override
    public void addValue(RedisDataInfo redisDataInfo) {
        StringRedisTemplate redisTemplate = redisService.getRedisTemplate(redisDataInfo);
        redisDataInfo.setType(redisTemplate.type(redisDataInfo.getKey()));
        switch (redisDataInfo.getType()) {
            case LIST:
                ListOperations<String, String> opsForList = redisTemplate.opsForList();
                opsForList.leftPush(redisDataInfo.getKey(), (String) redisDataInfo.getValue());
                break;
            case HASH:
                HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();
                List<String> list = (List<String>) redisDataInfo.getValue();
                opsForHash.put(redisDataInfo.getKey(), list.get(0), list.get(1));
                break;
            case SET:
                SetOperations<String, String> opsForSet = redisTemplate.opsForSet();
                opsForSet.add(redisDataInfo.getKey(), (String) redisDataInfo.getValue());
                break;
            case ZSET:
                List<String> list1 = (List<String>) redisDataInfo.getValue();
                ZSetOperations<String, String> opsForZSet = redisTemplate.opsForZSet();
                opsForZSet.add(redisDataInfo.getKey(), list1.get(0), Double.parseDouble(list1.get(1)));
        }
        redisTemplate.getConnectionFactory().getConnection().close();
    }

    @Override
    public void updateValue(RedisDataInfo redisDataInfo) {
        StringRedisTemplate redisTemplate = redisService.getRedisTemplate(redisDataInfo);
        String key = redisDataInfo.getKey();
        redisDataInfo.setType(redisTemplate.type(key));
        switch (redisDataInfo.getType()) {
            case STRING:
                ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
                opsForValue.set(key, (String) redisDataInfo.getValue());
                break;
            case LIST:
                List<String> list = (List<String>) redisDataInfo.getValue();
                ListOperations<String, String> opsForList = redisTemplate.opsForList();
                opsForList.set(key, Long.parseLong(list.get(0)), list.get(1));
                break;
            case HASH:
                List<String> list2 = (List<String>) redisDataInfo.getValue();
                HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();
                opsForHash.delete(key, list2.get(0));
                opsForHash.put(key, list2.get(1), list2.get(2));
                break;
            case SET:
                List<String> list1 = (List<String>) redisDataInfo.getValue();
                SetOperations<String, String> opsForSet = redisTemplate.opsForSet();
                opsForSet.remove(key, list1.get(0));
                opsForSet.add(key, list1.get(1));
                break;
            case ZSET:
                List<String> list3 = (List<String>) redisDataInfo.getValue();
                ZSetOperations<String, String> opsForZSet = redisTemplate.opsForZSet();
                opsForZSet.remove(key, list3.get(0));
                opsForZSet.add(key, list3.get(1), Double.parseDouble(list3.get(2)));
                break;
        }
        redisTemplate.getConnectionFactory().getConnection().close();
    }

    @Override
    public void deleteValue(RedisDataInfo redisDataInfo) {
        StringRedisTemplate redisTemplate = redisService.getRedisTemplate(redisDataInfo);

        switch (redisTemplate.type(redisDataInfo.getKey())) {
            case LIST:
                String value = (String) redisDataInfo.getValue();
                ListOperations<String, String> opsForList = redisTemplate.opsForList();
                opsForList.set(redisDataInfo.getKey(), Long.parseLong(value), "---VALUE_REMOVED_BY_RDM---");
                opsForList.remove(redisDataInfo.getKey(), 0, "---VALUE_REMOVED_BY_RDM---");
                break;
            case HASH:
                String key = (String) redisDataInfo.getValue();
                HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();
                opsForHash.delete(redisDataInfo.getKey(), key);
                break;
            case SET:
                String value1 = (String) redisDataInfo.getValue();
                SetOperations<String, String> opsForSet = redisTemplate.opsForSet();
                opsForSet.remove(redisDataInfo.getKey(), value1);
                break;
            case ZSET:
                String value2 = (String) redisDataInfo.getValue();
                ZSetOperations<String, String> opsForZSet = redisTemplate.opsForZSet();
                opsForZSet.remove(redisDataInfo.getKey(), value2);
        }
        redisTemplate.getConnectionFactory().getConnection().close();
    }


}
